package com.xhorse.lockplatform.aspect;

import com.xhorse.lockplatform.annotation.RequestLimit;
import com.xhorse.lockplatform.comm.constant.Constants;
import com.xhorse.lockplatform.comm.enums.ResultEnum;
import com.xhorse.lockplatform.comm.exception.LockPlatFormException;
import com.xhorse.lockplatform.comm.util.RequestUtils;
import com.xhorse.lockplatform.service.base.RedisService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Component
@Aspect
public class RequestAspect {

    private final static Logger logger = LoggerFactory.getLogger(RequestAspect.class);

    @Autowired
    private RedisService redisService;

    @Before("@annotation(com.xhorse.lockplatform.annotation.RequestLimit)")
    public void checkPermission(JoinPoint joinPoint) throws LockPlatFormException {
        try {
            Object[] args = joinPoint.getArgs();
            HttpServletRequest request = null;
            RequestLimit limit = this.getAnnotation(joinPoint);
            //获取HttpRequest
            for (int i = 0; i < args.length; i++) {
                if (args[i] instanceof HttpServletRequest) {
                    request = (HttpServletRequest) args[i];
                    break;
                }
            }
            //判断request不能为空
            if (request == null) {
                throw new LockPlatFormException(ResultEnum.FAILED.getCode(), "方法中缺失HttpServletRequest参数");
            }
            String ip = RequestUtils.getRemoteIp(request);
            String url = request.getRequestURL().toString();
            String key = Constants.REQ_LIMIT.concat(ip).concat(url);
            //设置在redis中的缓存，累加1
            int count = redisService.incrementFun(key, 1);
            //如果key不存在，则从0开始计算，并且当count为1的时候，设置过期时间
            if (count == 1) {
                redisService.set(key, count, limit.time());
            }
            //如果redis中的count大于限制的次数，则报错
            if (count > limit.count()) {
                logger.info("用户IP[" + ip + "]访问地址[" + url + "]超过了限定的次数[" + limit.count() + "]");
                throw new LockPlatFormException(ResultEnum.FAILED);
            }
        } catch (LockPlatFormException e) {
            throw e;
        } catch (Exception e) {
            logger.error("发生异常: ", e);
        }
    }

    /**
     * 获得注解
     *
     * @param joinPoint
     * @return
     * @throws Exception
     */
    private RequestLimit getAnnotation(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null) {
            return method.getAnnotation(RequestLimit.class);
        }
        return null;
    }
}
